package com.nanbei.a39;

import org.springframework.boot.DefaultBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

/**
 * @ClassDescription:
 * @JdkVersion: 1.8
 * @Author: libs
 * @Created: 2024/12/26 14:17
 */
@SpringBootApplication
public class A39_2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        SpringApplication application = new SpringApplication(A39_2.class);
        application.addListeners(event -> System.out.println(event.getClass()));

        // 获取事件发送器类名
        List<String> names = SpringFactoriesLoader.loadFactoryNames(SpringApplicationRunListener.class, A39_2.class.getClassLoader());
        for (String name : names) {
            System.out.println(name);
            Class<?> clazz = Class.forName(name);
            Constructor<?> constructor = clazz.getConstructor(SpringApplication.class, String[].class);
            SpringApplicationRunListener publish = (SpringApplicationRunListener) constructor.newInstance(application, args);

            //发布事件
            DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
            publish.starting(bootstrapContext);// spring boot 开始启动

            publish.environmentPrepared(bootstrapContext,new StandardEnvironment());// 环境信息准备完毕

            GenericApplicationContext context = new GenericApplicationContext();
            publish.contextPrepared(context) ; // 在spring 容器创建，并调用初始化之后，发送此事件

            publish.contextLoaded(context); // 所有 bean definition 加载完毕

            context.refresh();

            publish.started(context); // sping 容器初始化完成 （refresh 方法加载完毕）

            publish.running(context); // spring boot 启动完毕

            publish.failed(context,new Exception("加载出错了"));// spring boot 启动出错
        }
        application.run(args);
    }
}
